home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 32
/
Aminet 32 (1999)(Schatztruhe)[!][Aug 1999].iso
/
Aminet
/
dev
/
lang
/
Python152_Src.lha
/
Python152_Source
/
Modules
/
amigamodule.c
next >
Wrap
C/C++ Source or Header
|
1999-04-26
|
28KB
|
1,273 lines
/**************************************************************\
** **
** AMIGA module implementation, for SAS/C version 6.58 **
** **
** Made by Irmen de Jong (irmen@bigfoot.com) **
** **
** 27-mar-96: Added a lot of AmiTCP functions! **
** 2-apr-96: Many small fixes & enhancements. **
** 11-apr-96: Totally rewritten the environment handling. **
** Now creates 4 separate dictionaries. **
** Fixed link(), added symlink() and readlink(). **
** 29-may-96: Added filenote() and fullpath() **
** 11-jun-96: Moved filenote() to doslib/SetComment **
** 12-jun-96: Removed execv **
** 29-Aug-96: fixed getcwd(), some minor errno fixes **
** 26-Dec-96: upgraded to 1.4: added putenv(), remove() **
** fixed mkdir: default protbits (0777) **
** 6-Apr-97: fixed bug in readlink (lock was incorrect) **
** 6-Nov-97: added uname() **
** 12-Jan-98: upgraded to 1.5: fixed includes, new names, **
** uses new Amiga/.../unixemul.c **
** 28-Mar-98: fixed buffer overflow bug in convertenviron() **
** 27-Sep-98: added crc32 function **
** 24-Dec-98: moved bunch of #defines to config.h **
** 25-Dec-98: added I-Net 225 support **
** **
** Adapted from posixmodule.c; implements as much of the **
** functionality of this module as possible. **
** **
** **
** TO DO: Implement execv(e) and threads (if possible). **
** **
** NOTE: Don't forget __io2errno conversion!!!!!!!!!!!!!!!! **
** **
\**************************************************************/
#include "Python.h"
#include "osdefs.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stat.h>
#ifndef INET225
#include <dos.h>
#endif
#include <proto/dos.h>
#include <proto/exec.h>
#include <dos/dosextens.h>
#include <dos/var.h>
#include <dos/dostags.h>
#include <exec/execbase.h>
#include "mytime.h" /* For clock_t on some systems */
#ifdef HAVE_UTIME_H
#include <utime.h>
#endif
#include <dirent.h>
#define NAMLEN(dirent) strlen((dirent)->d_name)
#ifdef AMITCP
#include <clib/netlib_protos.h>
#endif
#ifdef INET225
#include <proto/socket.h>
static int _OSERR;
#define getegid() getgid()
#define geteuid() getuid()
static __inline int dup(int oldsd) { return s_dup(oldsd); }
static __inline int dup2(int oldsd, int newsd) { return s_dup2(oldsd, newsd); }
#endif
#include "protos.h"
/* Return a dictionary corresponding to the AmigaDOS environment table. */
/* That is, scan ENV: for global environment variables. */
/* The local shell environment variables are put into another table. */
static int
convertenviron(PyObject **glob, PyObject **loc,
PyObject **both, PyObject **aliases)
{
BPTR dlok;
struct FileInfoBlock __aligned fib;
PyObject *v;
char *dynbuf;
struct LocalVar *lvar;
struct List *localvars;
*glob=PyDict_New();
*loc=PyDict_New();
*both=PyDict_New();
*aliases=PyDict_New();
if(!*glob || !*loc || !*both || !*aliases)
{
if(*glob) Py_DECREF(*glob);
if(*loc) Py_DECREF(*loc);
if(*both) Py_DECREF(*both);
if(*aliases) Py_DECREF(*aliases);
return 0;
}
/* Read global vars from ENV: */
/* Put them in 'glob' and in 'both'. */
if(dlok=Lock("ENV:",ACCESS_READ))
{
if(Examine(dlok,&fib))
{
while(ExNext(dlok,&fib))
{
if(fib.fib_DirEntryType<0)
{
if(dynbuf=malloc(fib.fib_Size+1))
{
int len=GetVar(fib.fib_FileName,dynbuf,fib.fib_Size+1,GVF_GLOBAL_ONLY);
if(len>=0 && (v=PyString_FromString(dynbuf)))
{
PyDict_SetItemString(*glob,fib.fib_FileName,v);
PyDict_SetItemString(*both,fib.fib_FileName,v);
Py_DECREF(v);
}
free(dynbuf);
}
}
}
}
}
if(dlok) UnLock(dlok);
/* Scan the local shell environment, including "RC" and "Result2"! */
/* Put shell vars in 'loc' and 'both', and aliases in 'aliases'. */
/* Because of the fact that the inserting of local vars into 'both' */
/* happens AFTER the insertion of global vars, the formor overwrite */
/* the latter, and thus have higher priority (as it should be). */
localvars = (struct List*) &((struct Process*)FindTask(0))->pr_LocalVars;
if(!IsListEmpty(localvars))
{
lvar = (struct LocalVar*) localvars->lh_Head;
do {
if(dynbuf=malloc(lvar->lv_Len+1))
{
strncpy(dynbuf,lvar->lv_Value,lvar->lv_Len);
dynbuf[lvar->lv_Len]=0;
if(v=PyString_FromString(dynbuf))
{
if(lvar->lv_Node.ln_Type==LV_VAR)
{
PyDict_SetItemString(*loc,lvar->lv_Node.ln_Name,v);
PyDict_SetItemString(*both,lvar->lv_Node.ln_Name,v);
}
else if(lvar->lv_Node.ln_Type==LV_ALIAS)
PyDict_SetItemString(*aliases,lvar->lv_Node.ln_Name,v);
Py_DECREF(v);
}
free(dynbuf);
}
} while((lvar=(struct LocalVar*)lvar->lv_Node.ln_Succ)->lv_Node.ln_Succ);
}
return 1;
}
static PyObject *AmigaError; /* Exception amiga.error */
/* Set a Amiga-specific error from errno, and return NULL */
static PyObject * amiga_error(void)
{
return PyErr_SetFromErrno(AmigaError);
}
/* AMIGA generic methods */
static PyObject *
amiga_1str(PyObject *args, int (*func)(const char *))
{
char *path1;
int res;
if (!PyArg_Parse(args, "s", &path1))
return NULL;
Py_BEGIN_ALLOW_THREADS
res = (*func)(path1);
Py_END_ALLOW_THREADS
if (res < 0)
return amiga_error();
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
amiga_2str(PyObject *args, int (*func)(const char *, const char *))
{
char *path1, *path2;
int res;
if (!PyArg_Parse(args, "(ss)", &path1, &path2))
return NULL;
Py_BEGIN_ALLOW_THREADS
res = (*func)(path1, path2);
Py_END_ALLOW_THREADS
if (res < 0)
return amiga_error();
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
amiga_strint(PyObject *args, int (*func)(const char *, int))
{
char *path;
int i;
int res;
if (!PyArg_Parse(args, "(si)", &path, &i))
return NULL;
Py_BEGIN_ALLOW_THREADS
res = (*func)(path, i);
Py_END_ALLOW_THREADS
if (res < 0)
return amiga_error();
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
amiga_strintint(PyObject *args, int (*func)(const char *, int, int))
{
char *path;
int i,i2;
int res;
if (!PyArg_Parse(args, "(sii)", &path, &i, &i2))
return NULL;
Py_BEGIN_ALLOW_THREADS
res = (*func)(path, i, i2);
Py_END_ALLOW_THREADS
if (res < 0)
return amiga_error();
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
amiga_do_stat(PyObject *self, PyObject *args, int (*statfunc)(const char *, struct stat *))
{
struct stat st;
char *path;
int res;
if (!PyArg_Parse(args, "s", &path))
return NULL;
Py_BEGIN_ALLOW_THREADS
res = (*statfunc)(path, &st);
Py_END_ALLOW_THREADS
if (res != 0)
return amiga_error();
return Py_BuildValue("(llllllllll)",
(long)st.st_mode,
(long)st.st_ino,
(long)st.st_dev,
(long)st.st_nlink,
(long)st.st_uid,
(long)st.st_gid,
(long)st.st_size,
(long)st.st_atime,
(long)st.st_mtime,
(long)st.st_ctime);
}
/* AMIGA methods */
static PyObject *
amiga_chdir(PyObject *self, PyObject *args)
{
return amiga_1str(args, chdir);
}
static PyObject *
amiga_chmod(PyObject *self, PyObject *args)
{
return amiga_strint(args, chmod);
}
#ifdef HAVE_CHOWN
static PyObject *
amiga_chown(PyObject *self, PyObject *args)
{
return amiga_strintint(args, chown);
}
#endif /* HAVE_CHOWN */
#ifdef HAVE_GETCWD
static PyObject *
amiga_getcwd(PyObject *self, PyObject *args)
{
char buf[MAXPATHLEN];
char *res;
if (!PyArg_Parse(args,""))
return NULL;
Py_BEGIN_ALLOW_THREADS
res = getcwd(buf, sizeof buf);
Py_END_ALLOW_THREADS
if (res == NULL)
return amiga_error();
return PyString_FromString(buf);
}
#endif
#ifdef HAVE_LINK
static PyObject *
amiga_link(PyObject *self, PyObject *args)
{
return amiga_2str(args, link);
}
#endif
static PyObject *
amiga_listdir(PyObject *self, PyObject *args)
{
BPTR dlok;
char *name;
struct FileInfoBlock __aligned fib;
PyObject *d;
if (!PyArg_Parse(args, "s", &name)) return NULL;
if ((d = PyList_New(0)) == NULL) return NULL;
if(dlok=Lock(name,ACCESS_READ))
{
if(Examine(dlok,&fib))
{
while(ExNext(dlok,&fib))
{
PyObject *v = PyString_FromString(fib.fib_FileName);
if(v==NULL)
{
Py_DECREF(d); d=NULL; break;
}
if(PyList_Append(d,v)!=0)
{
Py_DECREF(v); Py_DECREF(d); d=NULL; break;
}
Py_DECREF(v);
}
}
UnLock(dlok);
}
if(IoErr()==ERROR_NO_MORE_ENTRIES) return d;
Py_DECREF(d);
errno=__io2errno(_OSERR=IoErr());
return amiga_error();
}
static PyObject *
amiga_mkdir(PyObject *self, PyObject *args)
{
int res;
char *path;
int mode = 0777;
if (!PyArg_ParseTuple(args, "s|i", &path, &mode)) return NULL;
Py_BEGIN_ALLOW_THREADS
#ifdef INET225
res = mkdir(path, mode);
#else
res = my_mkdir(path, mode);
#endif
Py_END_ALLOW_THREADS
if (res < 0) return amiga_error();
Py_INCREF(Py_None); return Py_None;
}
static PyObject *
amiga_rename(PyObject *self, PyObject *args)
{
return amiga_2str(args, rename);
}
static PyObject *
amiga_rmdir(PyObject *self, PyObject *args)
{
return amiga_1str(args, rmdir);
}
static PyObject *
amiga_stat(PyObject *self, PyObject *args)
{
return amiga_do_stat(self, args, stat);
}
#ifdef HAVE_SYSTEM
static PyObject *
amiga_system(PyObject *self, PyObject *args)
{
char *command;
long sts;
if (!PyArg_Parse(args, "s", &command))
return NULL;
Py_BEGIN_ALLOW_THREADS
sts = system(command);
Py_END_ALLOW_THREADS
return PyInt_FromLong(sts);
}
#endif
#if defined(AMITCP) || defined(INET225)
static PyObject *
amiga_umask(PyObject *self, PyObject *args)
{
int i;
#ifdef AMITCP
if (!checkusergrouplib()) return NULL;
#else
if (!checksocketlib()) return NULL;
#endif
if (!PyArg_Parse(args,"i",&i))
return NULL;
i = umask(i);
if (i < 0)
return amiga_error();
return PyInt_FromLong((long)i);
}
#endif
#ifdef HAVE_UNAME
static PyObject *
amiga_uname(PyObject *self, PyObject *args)
{
struct utsname u;
int res;
if (!PyArg_NoArgs(args))
return NULL;
Py_BEGIN_ALLOW_THREADS
res = uname(&u);
Py_END_ALLOW_THREADS
if (res < 0)
return amiga_error();
return Py_BuildValue("(sssss)",
u.sysname,
u.nodename,
u.release,
u.version,
u.machine);
}
#endif
static PyObject *
amiga_unlink(PyObject *self, PyObject *args)
{
return amiga_1str(args, unlink);
}
#if defined(AMITCP) || defined(INET225)
static PyObject *
amiga_utime(PyObject *self, PyObject *args)
{
char *path;
long atime, mtime;
int res;
#ifdef HAVE_UTIME_H
struct utimbuf buf;
#define ATIME buf.actime
#define MTIME buf.modtime
#define UTIME_ARG &buf
#else /* HAVE_UTIME_H */
time_t buf[2];
#define ATIME buf[0]
#define MTIME buf[1]
#define UTIME_ARG buf
#endif /* HAVE_UTIME_H */
if (!PyArg_Parse(args, "(s(ll))", &path, &atime, &mtime))
return NULL;
ATIME = atime;
MTIME = mtime;
Py_BEGIN_ALLOW_THREADS
res = utime(path, UTIME_ARG);
Py_END_ALLOW_THREADS
if (res < 0)
return amiga_error();
Py_INCREF(Py_None);
return Py_None;
#undef UTIME_ARG
#undef ATIME
#undef MTIME
}
#endif
/* Process operations */
/* XXX Removed _exit. You are VERY STUPID if you used this. (2-apr-96) */
/* XXX Removed execv. You must use system/exit combination instead. */
/* Maybe one day I'll implement a REAL execv ?? */
#ifdef HAVE_GETEGID
static PyObject *
amiga_getegid(PyObject *self, PyObject *args)
{
#ifdef AMITCP
if (!checkusergrouplib()) return NULL;
#else
if (!checksocketlib()) return NULL;
#endif
if (!PyArg_Parse(args,""))
return NULL;
return PyInt_FromLong((long)getegid());
}
#endif
#ifdef HAVE_GETEUID
static PyObject *
amiga_geteuid(PyObject *self, PyObject *args)
{
#ifdef AMITCP
if (!checkusergrouplib()) return NULL;
#else
if (!checksocketlib()) return NULL;
#endif
if (!PyArg_Parse(args,""))
return NULL;
return PyInt_FromLong((long)geteuid());
}
#endif
#ifdef HAVE_GETGID
static PyObject *
amiga_getgid(PyObject *self, PyObject *args)
{
#ifdef AMITCP
if (!checkusergrouplib()) return NULL;
#else
if (!checksocketlib()) return NULL;
#endif
if (!PyArg_Parse(args,""))
return NULL;
return PyInt_FromLong((long)getgid());
}
#endif
static PyObject *
amiga_getpid(PyObject *self, PyObject *args)
{
if (!PyArg_Parse(args,""))
return NULL;
return PyInt_FromLong((long)FindTask(0));
}
#ifdef HAVE_GETPGRP
static PyObject *
amiga_getpgrp(PyObject *self, PyObject *args)
{
#ifdef AMITCP
if (!checkusergrouplib()) return NULL;
#else
if (!checksocketlib()) return NULL;
#endif
if (!PyArg_Parse(args,""))
return NULL;
#ifdef GETPGRP_HAVE_ARG
return PyInt_FromLong((long)getpgrp(0));
#else /* GETPGRP_HAVE_ARG */
return PyInt_FromLong((long)getpgrp());
#endif /* GETPGRP_HAVE_ARG */
}
#endif /* HAVE_GETPGRP */
#ifdef HAVE_SETPGRP
static PyObject *
amiga_setpgrp(PyObject *self, PyObject *args)
{
#ifdef AMITCP
if (!checkusergrouplib()) return NULL;
#else
if (!checksocketlib()) return NULL;
#endif
if (!PyArg_Parse(args,""))
return NULL;
#ifdef SETPGRP_HAVE_ARG
if (setpgrp(0, 0) < 0)
#else /* SETPGRP_HAVE_ARG */
if (setpgrp() < 0)
#endif /* SETPGRP_HAVE_ARG */
return amiga_error();
Py_INCREF(Py_None);
return Py_None;
}
#endif /* HAVE_SETPGRP */
#ifdef HAVE_GETPPID
static PyObject *
amiga_getppid(PyObject *self, PyObject *args)
{
if (!PyArg_Parse(args,""))
return NULL;
return PyInt_FromLong((long)getppid());
}
#endif
#ifdef HAVE_GETUID
static PyObject *
amiga_getuid(PyObject *self, PyObject *args)
{
#ifdef AMITCP
if (!checkusergrouplib()) return NULL;
#else
if (!checksocketlib()) return NULL;
#endif
if (!PyArg_Parse(args,""))
return NULL;
return PyInt_FromLong((long)getuid());
}
#endif
#ifdef HAVE_POPEN
static PyObject *
amiga_popen(PyObject *self, PyObject *args)
{
char *name;
char *mode = "r";
int bufsize = -1;
FILE *fp;
PyObject *f;
if (!PyArg_ParseTuple(args, "s|si", &name, &mode, &bufsize))
return NULL;
Py_BEGIN_ALLOW_THREADS
fp = popen(name, mode);
Py_END_ALLOW_THREADS
if (fp == NULL)
return amiga_error();
f = PyFile_FromFile(fp, name, mode, pclose);
if (f != NULL)
PyFile_SetBufSize(f, bufsize);
return f;
}
#endif
#ifdef HAVE_SETUID
static PyObject *
amiga_setuid(PyObject *self, PyObject *args)
{
int uid;
#ifdef AMITCP
if (!checkusergrouplib()) return NULL;
#else
if (!checksocketlib()) return NULL;
#endif
if (!PyArg_Parse(args, "i", &uid))
return NULL;
if (setuid(uid) < 0)
return amiga_error();
Py_INCREF(Py_None);
return Py_None;
}
#endif /* HAVE_SETUID */
#ifdef HAVE_SETGID
static PyObject *
amiga_setgid(PyObject *self, PyObject *args)
{
int gid;
#ifdef AMITCP
if (!checkusergrouplib()) return NULL;
#else
if (!checksocketlib()) return NULL;
#endif
if (!PyArg_Parse(args, "i", &gid))
return NULL;
if (setgid(gid) < 0)
return amiga_error();
Py_INCREF(Py_None);
return Py_None;
}
#endif /* HAVE_SETGID */
static PyObject *
amiga_lstat(PyObject *self, PyObject *args)
{
#ifdef HAVE_LSTAT
return amiga_do_stat(self, args, lstat);
#else /* !HAVE_LSTAT */
return amiga_do_stat(self, args, stat);
#endif /* !HAVE_LSTAT */
}
#ifdef HAVE_READLINK
static PyObject *
amiga_readlink(PyObject *self, PyObject *args)
{
char buf[MAXPATHLEN];
char *path;
int n;
if (!PyArg_Parse(args, "s", &path))
return NULL;
Py_BEGIN_ALLOW_THREADS
n = readlink(path, buf, (int) sizeof buf);
Py_END_ALLOW_THREADS
if (n < 0)
return amiga_error();
return PyString_FromStringAndSize(buf, n);
}
#endif
#ifdef HAVE_SYMLINK
static PyObject *
amiga_symlink(PyObject *self, PyObject *args)
{
return amiga_2str(args, symlink);
}
#endif
#ifdef HAVE_SETSID
static PyObject *
amiga_setsid(PyObject *self, PyObject *args)
{
#ifdef AMITCP
if (!checkusergrouplib()) return NULL;
#else
if (!checksocketlib()) return NULL;
#endif
if (!PyArg_Parse(args,""))
return NULL;
if ((int)setsid() < 0)
return amiga_error();
Py_INCREF(Py_None);
return Py_None;
}
#endif /* HAVE_SETSID */
#ifdef HAVE_SETPGID
static PyObject *
amiga_setpgid(PyObject *self, PyObject *args)
{
int pid, pgrp;
if (!PyArg_Parse(args, "(ii)", &pid, &pgrp))
return NULL;
if (setpgid(pid, pgrp) < 0)
return amiga_error();
Py_INCREF(Py_None);
return Py_None;
}
#endif /* HAVE_SETPGID */
/* Functions acting on file descriptors */
static PyObject *
amiga_open(PyObject *self, PyObject *args)
{
char *file;
int flag;
int mode = 0777;
int fd;
if (!PyArg_Parse(args, "(si)", &file, &flag)) {
PyErr_Clear();
if (!PyArg_Parse(args, "(sii)", &file, &flag, &mode))
return NULL;
}
Py_BEGIN_ALLOW_THREADS
fd = open(file, flag, mode);
Py_END_ALLOW_THREADS
if (fd < 0)
return amiga_error();
return PyInt_FromLong((long)fd);
}
static PyObject *
amiga_close(PyObject *self, PyObject *args)
{
int fd, res;
if (!PyArg_Parse(args, "i", &fd))
return NULL;
Py_BEGIN_ALLOW_THREADS
res = close(fd);
Py_END_ALLOW_THREADS
if (res < 0)
return amiga_error();
Py_INCREF(Py_None);
return Py_None;
}
#if defined(AMITCP) || defined(INET225)
static PyObject *
amiga_dup(PyObject *self, PyObject *args)
{
int fd;
if (!checksocketlib()) { PyErr_Clear(); errno=EIO; return amiga_error(); }
if (!PyArg_Parse(args, "i", &fd))
return NULL;
Py_BEGIN_ALLOW_THREADS
fd = dup(fd);
Py_END_ALLOW_THREADS
if (fd < 0)
return amiga_error();
return PyInt_FromLong((long)fd);
}
static PyObject *
amiga_dup2(PyObject *self, PyObject *args)
{
int fd, fd2, res;
if (!checksocketlib()) { PyErr_Clear(); errno=EIO; return amiga_error(); }
if (!PyArg_Parse(args, "(ii)", &fd, &fd2))
return NULL;
Py_BEGIN_ALLOW_THREADS
res = dup2(fd, fd2);
Py_END_ALLOW_THREADS
if (res < 0)
return amiga_error();
Py_INCREF(Py_None);
return Py_None;
}
#endif
static PyObject *
amiga_lseek(PyObject *self, PyObject *args)
{
int fd, how;
long pos, res;
if (!PyArg_Parse(args, "(ili)", &fd, &pos, &how))
return NULL;
#ifdef SEEK_SET
/* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
switch (how) {
case 0: how = SEEK_SET; break;
case 1: how = SEEK_CUR; break;
case 2: how = SEEK_END; break;
}
#endif /* SEEK_END */
Py_BEGIN_ALLOW_THREADS
res = lseek(fd, pos, how);
Py_END_ALLOW_THREADS
if (res < 0)
return amiga_error();
return PyInt_FromLong(res);
}
static PyObject *
amiga_read(PyObject *self, PyObject *args)
{
int fd, size;
PyObject *buffer;
if (!PyArg_Parse(args, "(ii)", &fd, &size))
return NULL;
buffer = PyString_FromStringAndSize((char *)NULL, size);
if (buffer == NULL)
return NULL;
Py_BEGIN_ALLOW_THREADS
size = read(fd, PyString_AsString(buffer), size);
Py_END_ALLOW_THREADS
if (size < 0) {
Py_DECREF(buffer);
return amiga_error();
}
_PyString_Resize(&buffer, size);
return buffer;
}
static PyObject *
amiga_write(PyObject *self, PyObject *args)
{
int fd, size;
char *buffer;
if (!PyArg_Parse(args, "(is#)", &fd, &buffer, &size))
return NULL;
Py_BEGIN_ALLOW_THREADS
size = write(fd, buffer, size);
Py_END_ALLOW_THREADS
if (size < 0)
return amiga_error();
return PyInt_FromLong((long)size);
}
static PyObject *
amiga_fstat(PyObject *self, PyObject *args)
{
int fd;
struct stat st;
int res;
if (!PyArg_Parse(args, "i", &fd))
return NULL;
Py_BEGIN_ALLOW_THREADS
res = fstat(fd, &st);
Py_END_ALLOW_THREADS
if (res != 0)
return amiga_error();
return Py_BuildValue("(llllllllll)",
(long)st.st_mode,
(long)st.st_ino,
(long)st.st_dev,
(long)st.st_nlink,
(long)st.st_uid,
(long)st.st_gid,
(long)st.st_size,
(long)st.st_atime,
(long)st.st_mtime,
(long)st.st_ctime);
}
static PyObject *
amiga_fdopen(PyObject *self, PyObject *args)
{
int fd;
char *mode = "r";
int bufsize = -1;
FILE *fp;
PyObject *f;
if (!PyArg_ParseTuple(args, "i|si", &fd, &mode, &bufsize))
return NULL;
Py_BEGIN_ALLOW_THREADS
fp = fdopen(fd, mode);
Py_END_ALLOW_THREADS
if (fp == NULL)
return amiga_error();
f = PyFile_FromFile(fp, "(fdopen)", mode, fclose);
if (f != NULL)
PyFile_SetBufSize(f, bufsize);
return f;
}
#if 0
/*** XXX pipe() is useless without fork() or threads ***/
/*** TODO: guess what.. implement threads! ***/
static int pipe(int *fildes)
{
/* 0=ok, -1=err, errno=EMFILE,ENFILE,EFAULT */
char buf[50];
static int num = 1;
sprintf(buf,"PIPE:Py%ld_%ld",FindTask(0),num++);
fildes[0]=open(buf,O_RDONLY,0);
if(fildes[0]>0)
{
fildes[1]=open(buf,O_WRONLY|O_CREAT,FIBF_OTR_READ|FIBF_OTR_WRITE);
if(fildes[1]>0)
{
return 0;
}
close(fildes[0]);
}
return -1;
}
static PyObject *
amiga_pipe(PyObject *self, PyObject *args)
{
int fds[2];
int res;
if (!PyArg_Parse(args, ""))
return NULL;
Py_BEGIN_ALLOW_THREADS
res = pipe(fds);
Py_END_ALLOW_THREADS
if (res != 0)
return amiga_error();
return Py_BuildValue("(ii)", fds[0], fds[1]);
}
#endif
static PyObject *
amiga_fullpath(PyObject *self, PyObject *args)
{
BOOL ok=FALSE;
BPTR lk;
char *path;
char buf[MAXPATHLEN];
if (!PyArg_ParseTuple(args, "s", &path)) return NULL;
Py_BEGIN_ALLOW_THREADS
if(lk=Lock(path,SHARED_LOCK))
{
ok=NameFromLock(lk,buf,sizeof(buf));
UnLock(lk);
}
Py_END_ALLOW_THREADS
if(!ok)
{
errno=__io2errno(_OSERR=IoErr());
return amiga_error();
}
else return PyString_FromString(buf);
}
static PyObject *amiga_putenv(PyObject *self, PyObject *args)
{
char *s1, *s2;
if (!PyArg_ParseTuple(args, "ss", &s1, &s2)) return NULL;
if(setenv(s1,s2,1))
{
amiga_error(); return NULL;
}
Py_INCREF(Py_None); return Py_None;
}
#ifdef HAVE_STRERROR
static char posix_strerror__doc__[] =
"strerror(code) -> string\n\
Translate an error code to a message string.";
PyObject *
amiga_strerror(PyObject *self, PyObject *args)
{
int code;
char *message;
if (!PyArg_ParseTuple(args, "i", &code))
return NULL;
message = strerror(code);
if (message == NULL) {
PyErr_SetString(PyExc_ValueError,
"strerror code out of range");
return NULL;
}
return PyString_FromString(message);
}
#endif /* strerror */
// external function prototype:
unsigned long __asm CalcCRC32(register __a1 const void *data, register __d1 unsigned long size);
PyObject *
amiga_crc32(PyObject *self, PyObject *args)
{
PyObject *py_str;
if(!PyArg_ParseTuple(args,"S",&py_str)) return NULL;
return PyInt_FromLong(CalcCRC32(PyString_AsString(py_str), PyString_Size(py_str)));
}
static struct PyMethodDef amiga_methods[] = {
{"chdir", amiga_chdir},
{"chmod", amiga_chmod},
#ifdef HAVE_CHOWN
{"chown", amiga_chown},
#endif
#ifdef HAVE_GETCWD
{"getcwd", amiga_getcwd},
#endif
{"fullpath", amiga_fullpath,1},
#ifdef HAVE_LINK
{"link", amiga_link},
#endif
{"listdir", amiga_listdir},
{"lstat", amiga_lstat},
{"mkdir", amiga_mkdir , 1},
#ifdef HAVE_READLINK
{"readlink", amiga_readlink},
#endif
{"rename", amiga_rename},
{"rmdir", amiga_rmdir},
{"stat", amiga_stat},
#ifdef HAVE_SYMLINK
{"symlink", amiga_symlink},
#endif
#ifdef HAVE_SYSTEM
{"system", amiga_system},
#endif
#if defined(AMITCP) || defined(INET225)
{"umask", amiga_umask},
#endif
#ifdef HAVE_UNAME
{"uname", amiga_uname},
#endif
{"unlink", amiga_unlink},
{"remove", amiga_unlink},
#if defined(AMITCP) || defined(INET225)
{"utime", amiga_utime},
#endif
#ifdef HAVE_TIMES
{"times", amiga_times},
#endif
#ifdef HAVE_EXECV
{"execv", amiga_execv},
{"execve", amiga_execve},
#endif /* HAVE_EXECV */
#ifdef HAVE_GETEGID
{"getegid", amiga_getegid},
#endif
#ifdef HAVE_GETEUID
{"geteuid", amiga_geteuid},
#endif
#ifdef HAVE_GETGID
{"getgid", amiga_getgid},
#endif
{"getpid", amiga_getpid},
#ifdef HAVE_GETPGRP
{"getpgrp", amiga_getpgrp},
#endif
#ifdef HAVE_GETPPID
{"getppid", amiga_getppid},
#endif
#ifdef HAVE_GETUID
{"getuid", amiga_getuid},
#endif
#ifdef HAVE_POPEN
{"popen", amiga_popen, 1},
#endif
#ifdef HAVE_SETUID
{"setuid", amiga_setuid},
#endif
#ifdef HAVE_SETGID
{"setgid", amiga_setgid},
#endif
#ifdef HAVE_SETPGRP
{"setpgrp", amiga_setpgrp},
#endif
#ifdef HAVE_SETSID
{"setsid", amiga_setsid},
#endif
#ifdef HAVE_SETPGID
{"setpgid", amiga_setpgid},
#endif
#ifdef HAVE_TCGETPGRP
{"tcgetpgrp", amiga_tcgetpgrp},
#endif
#ifdef HAVE_TCSETPGRP
{"tcsetpgrp", amiga_tcsetpgrp},
#endif
{"open", amiga_open},
{"close", amiga_close},
#if defined(AMITCP) || defined(INET225)
{"dup", amiga_dup},
{"dup2", amiga_dup2},
#endif
{"lseek", amiga_lseek},
{"read", amiga_read},
{"write", amiga_write},
{"fstat", amiga_fstat},
{"fdopen", amiga_fdopen, 1},
#ifdef HAVE_MKFIFO
{"mkfifo", amiga_mkfifo, 1},
#endif
#ifdef HAVE_FTRUNCATE
{"ftruncate", amiga_ftruncate, 1},
#endif
#ifdef HAVE_PUTENV
{"putenv", amiga_putenv, 1},
#endif
#ifdef HAVE_STRERROR
{"strerror", amiga_strerror, 1},
#endif
#if 0
/* XXX TODO: implement threads. Otherwise pipe() is useless. */
{"pipe", amiga_pipe},
#endif
{"crc32", amiga_crc32, 1},
{NULL, NULL} /* Sentinel */
};
static int
ins(PyObject *d, char *symbol, long value)
{
PyObject* v = PyInt_FromLong(value);
if (!v || PyDict_SetItemString(d, symbol, v) < 0)
return -1; /* triggers fatal error */
Py_DECREF(v);
return 0;
}
static int all_ins(PyObject *d)
{
#ifdef WNOHANG
if (ins(d, "WNOHANG", (long)WNOHANG)) return -1;
#endif
#ifdef O_RDONLY
if (ins(d, "O_RDONLY", (long)O_RDONLY)) return -1;
#endif
#ifdef O_WRONLY
if (ins(d, "O_WRONLY", (long)O_WRONLY)) return -1;
#endif
#ifdef O_RDWR
if (ins(d, "O_RDWR", (long)O_RDWR)) return -1;
#endif
#ifdef O_NDELAY
if (ins(d, "O_NDELAY", (long)O_NDELAY)) return -1;
#endif
#ifdef O_NONBLOCK
if (ins(d, "O_NONBLOCK", (long)O_NONBLOCK)) return -1;
#endif
#ifdef O_APPEND
if (ins(d, "O_APPEND", (long)O_APPEND)) return -1;
#endif
#ifdef O_DSYNC
if (ins(d, "O_DSYNC", (long)O_DSYNC)) return -1;
#endif
#ifdef O_RSYNC
if (ins(d, "O_RSYNC", (long)O_RSYNC)) return -1;
#endif
#ifdef O_SYNC
if (ins(d, "O_SYNC", (long)O_SYNC)) return -1;
#endif
#ifdef O_NOCTTY
if (ins(d, "O_NOCTTY", (long)O_NOCTTY)) return -1;
#endif
#ifdef O_CREAT
if (ins(d, "O_CREAT", (long)O_CREAT)) return -1;
#endif
#ifdef O_EXCL
if (ins(d, "O_EXCL", (long)O_EXCL)) return -1;
#endif
#ifdef O_TRUNC
if (ins(d, "O_TRUNC", (long)O_TRUNC)) return -1;
#endif
#ifdef O_BINARY
if (ins(d, "O_BINARY", (long)O_BINARY)) return -1;
#endif
#ifdef O_TEXT
if (ins(d, "O_TEXT", (long)O_TEXT)) return -1;
#endif
#if defined(PYOS_OS2)
if (insertvalues(d)) return -1;
#endif
return 0;
}
void
initamiga(void)
{
PyObject *m, *d, *globv, *locv, *bothv, *aliases;
m = Py_InitModule("amiga", amiga_methods);
d = PyModule_GetDict(m);
/* Initialize amiga.environ dictionary */
if(!convertenviron(&globv, &locv, &bothv, &aliases))
Py_FatalError("can't read environment");
if (PyDict_SetItemString(d, "environ", bothv) != 0)
Py_FatalError("can't define amiga.environ");
Py_DECREF(bothv);
if (PyDict_SetItemString(d, "globalvars", globv) != 0)
Py_FatalError("can't define amiga.globalvars");
Py_DECREF(globv);
if (PyDict_SetItemString(d, "shellvars", locv) != 0)
Py_FatalError("can't define amiga.shellvars");
Py_DECREF(locv);
if (PyDict_SetItemString(d, "shellaliases", aliases ) != 0)
Py_FatalError("can't define amiga.shellaliases");
Py_DECREF(aliases);
if(all_ins(d)) return;
/* Initialize exception */
AmigaError = PyErr_NewException("os.error", NULL, NULL);
if (AmigaError != NULL)
PyDict_SetItemString(d, "error", AmigaError);
}